﻿#pragma once

#include <string>
#include <wtypes.h>
#include <algorithm>
#include <functional>
#include <vector>

#pragma warning(disable:4996)

#ifdef _UNICODE
typedef std::wstring xstring;
#else
typedef std::string xstring;
#endif

//循环左移
#define CROL(value, bits) ((value << bits) | (value >> (0x20 - bits)))
//循环右移:
#define CROR(value, bits) ((value >> bits) | (value << (0x20 - bits)))

#ifdef WIN32

#define GET_CALLADDR   	DWORD _EBP; \
						DWORD call_addr; \
						__asm mov _EBP, ebp; \
						call_addr = *(PDWORD)(_EBP+4);

#define GET_NEXTEBP   DWORD _NEBP = *(PDWORD)(_EBP+0);

#endif

namespace XUtil
{
	extern const char* czws;
	extern const wchar_t* wzws;



	bool fileIsExist(const xstring &_path);

	bool IsDirectory(const TCHAR* filename);

	xstring GetProgramPath(HINSTANCE hModule);

	xstring GetProgramDir(HINSTANCE hModule);

	//Converting a WChar string to a Ansi string
	std::string WChar2Ansi(LPCWSTR pwszSrc);

	std::string ws2s(std::wstring& inputws);

	//Converting a Ansi string to WChar string

	std::wstring Ansi2WChar(LPCSTR pszSrc, int nLen);

	std::wstring s2ws(const std::string& s);

	// trim from end of string (right)
	inline std::string& rtrim(std::string& s, const char* t = czws)
	{
		s.erase(s.find_last_not_of(t) + 1);
		return s;
	}

	// trim from beginning of string (left)
	inline std::string& ltrim(std::string& s, const char* t = czws)
	{
		s.erase(0, s.find_first_not_of(t));
		return s;
	}

	// trim from both ends of string (left & right)
	inline std::string& trim(std::string& s, const char* t = czws)
	{
		return ltrim(rtrim(s, t), t);
	}

	inline std::wstring& rtrim(std::wstring& s, const wchar_t* t)
	{
		s.erase(s.find_last_not_of(t) + 1);
		return s;
	}

	// trim from beginning of string (left)
	inline std::wstring& ltrim(std::wstring& s, const wchar_t* t)
	{
		s.erase(0, s.find_first_not_of(t));
		return s;
	}

	// trim from both ends of string (left & right)
	inline std::wstring& trim(std::wstring& s, const wchar_t* t)
	{
		return ltrim(rtrim(s, t), t);
	}

	void split(std::string& s, std::string& delim, std::vector<std::string>& ret);
	void split(std::wstring& s, std::wstring& delim, std::vector<std::wstring>& ret);

	std::string hex2str(const unsigned char *pData, int size, char chSpan=0x20, int lineSize=16);
	void hex2asc(unsigned char *hex, int hexlength, unsigned char *asc);
	int str2hex(const char *s, unsigned char *h, int slen = -1);

	bool haveNoAscii(const char* pstr, int len);

	template<typename  T>
	T GetDir(T strPath)
	{
		int nPos = strPath.rfind('\\');
		if (nPos == T::npos)
			return strPath;
		return strPath.substr(0, nPos + 1);
	}

	template<typename  T>
	T GetFilename(T strPath, bool withExt)
	{
		int nPos = strPath.rfind('\\');
		if (nPos == T::npos)
			return strPath;

		T filename = strPath.substr(nPos + 1);
		if (!withExt)
		{
			nPos = filename.rfind('.');
			if (nPos == T::npos)
				return filename;
			filename = filename.substr(0, nPos);
		}
		return filename;
	}

	template<typename  T>
	T GetFileExt(T strPath)
	{
		int nPos = strPath.rfind('.');
		if (nPos == T::npos)
			return T();
		return strPath.substr(nPos + 1);
	}

	std::string toString(UINT uV, int alignLen = 0, int base=16);
	std::string toString64(LONGLONG uV, int alignLen = 0, int base=16);
	std::string toStringF(float uV);

	void MakeLower(std::string &strsrc);

	void MakeUpper(std::string &strsrc);

	void StringReplace(std::string &strBase, std::string strSrc, std::string strDes);

	std::string GetNameWithDir(std::string path, int back_level);

	int32_t mkDirs(const xstring &directoryPath);

#ifdef WIN32
	inline DWORD GetAddrModuleName(PVOID addr, char* szModule, int len);
	std::string GetAddrModuleFileTitle(PVOID addr, int *ret = NULL);
	DWORD GetAddrOffset(DWORD addr);
	std::string GetCallStack(DWORD _EBP, int nDeep = 3);
	DWORD SafeGet(void* addr, int size = 4);
	void trav_dir(xstring path, const std::function<int(const char*)> &process_func);

	// 过滤器格式 "kt Flie\0*.kt;\0所有文件\0*.*\0\0";
	xstring ShowOpenfile(LPCTSTR filter, LPCTSTR title = NULL, LPCTSTR initDir = NULL);

	std::string GBK2UTF8(char *szGbk);
	std::string UTF82GBK(char *szUtf8);
#endif // WIN32

};
